package com.baide.sanguanheyi.ct;

import com.baide.sanguanheyi.interfaces.ChannelHandlerHolder;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.socket.SocketChannel;
import io.netty.util.Timeout;
import io.netty.util.Timer;
import io.netty.util.TimerTask;

import java.util.concurrent.TimeUnit;

@ChannelHandler.Sharable
public abstract class ConnectionWatchdog extends ChannelInboundHandlerAdapter implements TimerTask, ChannelHandlerHolder {

    private final Bootstrap bootstrap;
    private final Timer timer;
    private final int port;
    private final String host;
    private volatile boolean reconnect = true;
    private int attempts;
    private int connectCount;
    private int connectTime;

    public ConnectionWatchdog(Bootstrap bootstrap, Timer timer, int port, String host, boolean reconnect, int connectCount, int connectTime) {
        this.bootstrap = bootstrap;
        this.timer = timer;
        this.port = port;
        this.host = host;
        this.reconnect = reconnect;
        this.connectCount = connectCount;
        this.connectTime = connectTime;
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("当前链路已经激活，重新尝试连接次数重置为0");
        attempts = 0;
        ctx.fireChannelActive();
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("链路关闭");
        if (reconnect) {
            System.out.println("链路关闭，进行重连...");
            if (attempts < connectCount) {
                attempts++;
                // 重连的时间间隔越来越长
                int timeout = 2 << attempts;
                System.out.println(attempts);
                timer.newTimeout(this, connectTime, TimeUnit.SECONDS);
            }
        }
        ctx.fireChannelInactive();
    }

    ChannelFuture future;

    @Override
    public void run(Timeout timeout) throws Exception {

        // bootstrap 已经初始化结束，只需将handler传入即可
        synchronized (bootstrap) {
            bootstrap.handler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel ch) throws Exception {
                    ch.pipeline().addLast(handlers());
                }
            });
            future = bootstrap.connect(host, port);
        }
        future.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture f) throws Exception {
                boolean succeed = f.isSuccess();
                if (!succeed) { // 如果重连失败，再次发出重连事件
                    System.out.println("ct重连失败");
                    f.channel().pipeline().fireChannelInactive();
                } else {
                    System.out.println("ct重连成功");
                }
            }
        });

        System.out.println("ct timeout task : " + attempts);
    }

    public Channel getChanel() {
        if (future != null) {
            return future.channel();
        }
        return null;
    }

}
